package com.juitar.base;

import java.util.StringTokenizer;

public class Chord {

    private final String _name;
    private final int _root;
    private final int[] _notes;

    public Chord(String name, int[] notes, int root) {
        this._notes = notes;
        this._name = name;
        this._root = root;
    }

    public Chord(String name, int[] notes) {
        this(name, notes, 0);
    }

    public Chord(Chord chord, int root) {
        this(chord.getName(), chord.getNotes(), root);
    }

    /**
     * @return number of notes in this chord
     */
    public int numOfNotes() {
        return _notes.length;
    }

    public String getChordName() {
        return Note.toString(_root) + _name;
    }

    public String getName() {
        return _name;
    }

    public int getRootNote() {
        return _root;
    }
    
    
    public int[] getNotes() {
        return _notes;
    }

    /**
     * Checks if this chord contains given note
     * 
     * @param note note to check
     * @return 0 - if chord does not contain given note or index+1 of given
     *         note.
     */
    public int contains(int note) {
        int[] notes = getNotes();
        for (int i = 0; i < notes.length; i++) {
            if (Note.equals(notes[i] + _root, note)) return i + 1;
        }
        return 0;
    }

    /**
     * Factory method to create chords from the strings
     * 
     * @param chord chord definition <br>
     *        </code> chord_name = note note ... </code>
     * @return ChordBase object
     */
    public static Chord create(String chord) {
        int pos = chord.indexOf("=");
        if (pos >= 0) {
            String chordName = chord.substring(0, pos).trim();
            StringTokenizer t = new StringTokenizer(chord.substring(pos + 1), ",;- \t\n\r\f");
            int[] notes = new int[t.countTokens()];
            for (int i = 0; i < notes.length; i++) {
                String stringNote = t.nextToken();
                notes[i] = Integer.valueOf(stringNote).intValue();
            }
            return new Chord(chordName, notes);
        } else {
            throw new IllegalArgumentException("Bad chord-" + chord);
        }
    }

    public String getNotesText() {
        StringBuffer sb = new StringBuffer();
        int[] notes = getNotes();
        for (int i = 0; i < notes.length; i++) {
            sb.append(Note.toString(_root + notes[i])).append(" ");
        }
        sb.setLength(sb.length() - 1);
        return sb.toString();
    }

    public String toString() {
        return getName() + " [" + getNotesText() + "]";
    }

    public static final Chord MAJOR = new Chord("major", new int[] { 0, 4, 7 });
    public static final Chord MINOR = new Chord("minor", new int[] { 0, 3, 7 });
    public static final Chord SEVENTH = new Chord("7", new int[] { 0, 4, 7, 10 });
}